package pl.umk.mat.fred.unicore.urc.storagemanagement.actions;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;

import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.CatalogNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.GridNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.MultiplyCatalogNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.Node;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.StorageNode;

public class DoubleClickAction extends Action {
	
	private TreeViewer viewer;
	
	public DoubleClickAction(TreeViewer viewer) {
		super();
		this.viewer = viewer;
	}
	
	public void run() {
		ISelection selection = viewer.getSelection();
		Object obj = ((IStructuredSelection)selection).getFirstElement();
		run((Node) obj);
	}
	
	
	// run without creating new Job
	public void runOnThisThread(Node n) {
		if (n instanceof CatalogNode) {
			CatalogNode cn = (CatalogNode) n;
			cn.listCatalog();
			cn.setOpened(true);
		} else if (n instanceof StorageNode) {
			StorageNode sn = (StorageNode) n;
			sn.listStorage();
		}
	}
	
	public void run(final Node n) {
		run(n, true);
	}
	
	public void run(final Node n, final boolean expandTree) {
		if (n instanceof GridNode) {
			final GridNode node = (GridNode) n;
			for (Node sn : node.getChildren()) {
				if (!(sn instanceof StorageNode)) {
					continue;
				}
				this.run(sn);
			}
		} else if (n instanceof CatalogNode) {
			final CatalogNode node = (CatalogNode) n;
			Job job = new Job("List catalog") {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					monitor.beginTask("", IProgressMonitor.UNKNOWN);
					node.listCatalog();
					node.setOpened(true);
					if (!node.getRootNode().areStoragesVisible() && node.getMultiplyCatalogNode() != null) {
						refreshTree(node.getMultiplyCatalogNode(), expandTree ? 1 : 0);
					} else {
						refreshTree(node, expandTree ? 1 : 0);
					}
					refreshTree(node, expandTree ? 1 : 0);
					monitor.done();
					return Status.OK_STATUS;
				}
			};
			job.schedule();
		} else if (n instanceof MultiplyCatalogNode) {
			final MultiplyCatalogNode node = (MultiplyCatalogNode) n;
			Job job = new Job("List Catalog"){
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					monitor.beginTask("", node.getCatalogs().size());
					for (CatalogNode cn : node.getCatalogs()) {
						if (monitor.isCanceled()) {
							return Status.CANCEL_STATUS;
						}
						cn.listCatalog();
						monitor.worked(1);
					}
					node.setOpened(true);
					refreshTree(node, expandTree ? 1 : 0);
					monitor.done();
					return Status.OK_STATUS;
				}
			};
			job.schedule();
		} else if (n instanceof StorageNode) {
			final StorageNode node = (StorageNode) n;
			Job job = new Job("List storage") {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					monitor.beginTask("", IProgressMonitor.UNKNOWN);
					try {
						Long space = node.getStorage().getAvailableSpace();
						node.setFreeSpace(space);
					} catch (Exception e) {
						e.printStackTrace();
						return Status.CANCEL_STATUS;
					}
					node.listStorage();
					Node toRefresh = node.getRootNode().areStoragesVisible() ? node : node.getParent();
					refreshTree(toRefresh, expandTree ? 1 : 0);
					monitor.done();
					return Status.OK_STATUS;
				}
			};
			job.schedule();
		} 
	}
	
	private void refreshTree(final Node n, final int expandLevel) {
		Display display = PlatformUI.getWorkbench().getDisplay();
		display.asyncExec(new Runnable() {
			@Override
			public void run() {
				if ((viewer != null) && !viewer.getControl().isDisposed()) {
					viewer.refresh(n);
					viewer.expandToLevel(n, expandLevel);
				}
			}
		});
	}
}
